package com.coocare.licence.config.plugins.logging.aspect;

import com.alibaba.fastjson2.JSONObject;
import com.coocare.licence.config.i18n.I18nMessage;
import com.coocare.licence.config.plugins.logging.annotation.Logging;
import com.coocare.licence.config.plugins.logging.factory.LoggingFactory;
import com.coocare.licence.entity.SysLog;
import com.coocare.licence.utils.EmptyUtil;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.lang.reflect.Method;

@Aspect
@Component
@RequiredArgsConstructor
public class LoggingAspect {

    private final LoggingFactory loggingFactory;

    /**
     * 处理完请求后执行
     *
     * @param joinPoint 切点
     */
    @AfterReturning(value = "@annotation(logging)", returning = "returnValue")
    public void doAfterReturning(JoinPoint joinPoint, Logging logging, Object returnValue) {
        handleLog(joinPoint, returnValue, null);
    }

    /**
     * 处 理 系 统 日 志
     */
    @AfterThrowing(value = "@annotation(logging)", throwing = "e")
    private void doAfterReturning(JoinPoint joinPoint, Logging logging, Exception e) {
        handleLog(joinPoint, null, e);
    }

    private void handleLog(JoinPoint joinPoint, Object returnValue, Exception e) {
        SysLog logging = new SysLog();

        // 获取请求参数进行打印
        //Signature signature = joinPoint.getSignature();
        //JSONObject signatureJson = JSON.parseObject(JSON.toJSONString(signature));
        //JSONArray parameterNames = signatureJson.getJSONArray("parameterNames");

        // 接收到请求，记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        try {
            Logging loggingAnnotation = getLogging(joinPoint);
            logging.setTitle(I18nMessage.getMessage(loggingAnnotation.value()));
            logging.setRemoteAddr(request.getRemoteHost());
            logging.setRequestUri(request.getRequestURI());
            logging.setMethod(request.getMethod());
            logging.setParams(!EmptyUtil.isEmpty(request.getQueryString()) ? request.getQueryString() : JSONObject.toJSONString(joinPoint.getArgs()));
            if (e != null) {
                // 是 否 成 功
                logging.setException(StringUtils.substring(e.getMessage(), 0, 2000));
            }
        } catch (Exception exception) {
            logging.setException(StringUtils.substring(e.getMessage(), 0, 2000));
            throw exception;
        } finally {
            loggingFactory.record(logging, attributes);
        }
    }

    /**
     * 获 取 注 解
     */
    public Logging getLogging(JoinPoint point) {
        MethodSignature signature = (MethodSignature) point.getSignature();
        Class<? extends Object> targetClass = point.getTarget().getClass();
        Logging targetLogging = targetClass.getAnnotation(Logging.class);
        if (targetLogging != null) {
            return targetLogging;
        } else {
            Method method = signature.getMethod();
            Logging logging = method.getAnnotation(Logging.class);
            return logging;
        }
    }
}
